﻿#ifndef DAABSTRACTNODE_H
#define DAABSTRACTNODE_H
#include <memory>
#include "DAWorkFlowGlobal.h"
#include "DADataPackage.h"
#include "DANodeMetaData.h"

class DAAbstractNodeGraphicsItem;

DA_IMPL_FORWARD_DECL(DAAbstractNode)

/**
 * @brief 节点对应的基类
 *
 * 节点可以理解为一个函数，函数有多个输入，但只会有一个return或者多个分支的return，
 * 反映到节点中就是可以存在多个输入，但也应该有多个输出（参考流程中的菱形控制（if-else））。
 * 因此节点的输入点是0~n，节点的输出点是0~n。
 *
 *
 *
 * 需要用户实现以下6个函数
 * @code
 * //获取所有输入的参数名
 * virtual QList<QString> getInputKeys() const = 0;
 * //获取所有输出的参数名
 * virtual QList<QString> getOutputKeys() const = 0;
 * //节点对应的item显示接口，所有node都需要提供一个供前端的显示接口
 * virtual FCAbstractNodeGraphicsItem *createGraphicsItem();
 * //输出参数
 * virtual FCDataPackage output(const QString& ouputkey) = 0;
 * @endcode
 *
 *
 *
 */

class DAWORKFLOW_API DAAbstractNode : public std::enable_shared_from_this<DAAbstractNode>
{
    DA_IMPL(DAAbstractNode)
    friend class DAAbstractNodeGraphicsItem;

public:
    enum NodeAction {
        NodeInputed ///< 节点有输入完成，调用input方法会触发此动作,传递的value为input的值
    };
    using SharedPointer = std::shared_ptr<DAAbstractNode>;
    using WeakPointer = std::weak_ptr<DAAbstractNode>;

public:
    DAAbstractNode();
    virtual ~DAAbstractNode();

    //获取node的名字
    QString getNodeName() const;
    void setNodeName(const QString &name);

    //获取node的类型，这个类型可以表征同一类型的node 这个不会进行翻译
    QString getNodePrototype() const;

    //获取图标，图标是节点对应的图标
    QIcon getIcon() const;
    void setIcon(const QIcon &icon);

    //获取节点的元数据
    const DANodeMetaData &metaData() const;
    DANodeMetaData &metaData();

    //设置元数据
    void setMetaData(const DANodeMetaData &metadata);

    //返回自身智能指针
    SharedPointer pointer();

public: //连接相关
    //获取所有输入的参数名
    virtual QList<QString> getInputKeys() const = 0;

    //获取所有输出的参数名
    virtual QList<QString> getOutputKeys() const = 0;

    //建立连接,如果基础的对象需要校验，可继承此函数
    virtual bool linkTo(const QString &outpt, SharedPointer toItem, const QString &inpt);

    //移除连接,把输出节点对应的连接解除
    bool detachToLink(const QString &outpt);

    //移除所有依赖，一般是节点被删除时会调用此函数
    void detachAll();

public:
    //节点对应的item显示接口，所有node都需要提供一个供前端的显示接口
    virtual DAAbstractNodeGraphicsItem *createGraphicsItem() = 0;

    //获取node对应的item
    DAAbstractNodeGraphicsItem *graphicsItem();

    //获取node对应的item
    const DAAbstractNodeGraphicsItem *graphicsItem() const;

public:
    //数据操作
    //输入参数
    void input(const QString &key, DADataPackage dp);

    //获取input的数据包,此函数返回的FCDataPackage是引用，不发生拷贝，修改将直接改变input所维护的FCDataPackage内容
    DADataPackage inputData(const QString &key);

    //输出参数
    virtual DADataPackage output(const QString &ouputkey) = 0;

protected:
    //注册item，node的几个生命周期将会反馈到item中，destory
    void registGraphicsItem(DAAbstractNodeGraphicsItem *item);

    //调用此函数，将会在
    void callItemNodeHasAction(NodeAction act, const QVariant &v);
};

#endif // FCABSTRACTNODE_H
